package com.legendframework.core.dao.yaml;

import com.legendframework.core.dao.DefaultEntityValue;
import com.legendframework.core.dao.exception.DaoException;
import com.legendframework.core.dao.page.Page;
import com.legendframework.core.dao.page.PageUtil;
import com.legendframework.core.dao.support.ClassUtils;
import com.legendframework.core.dao.transaction.YamlTransaction;
import com.legendframework.core.dao.wrapper.Wrapper;
import com.legendframework.core.dao.yaml.support.BaseYml;
import com.legendframework.core.dao.yaml.support.IBaseYml;

import java.io.File;
import java.io.Serializable;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * YamlDao实现层
 *
 * @param <T> 实体类类型
 */
public class DefaultOneToOneYamlDaoImpl<T> extends AbstractYamlDao<T> {

    /**
     * Yaml底层实现
     */
    private IBaseYml<T> baseYml;

    /**
     * 用于反射创建对象是所需的空参构造
     */
    public DefaultOneToOneYamlDaoImpl() {
        super(null,null);
    }

    /**
     * 构造器
     * @param path 文件的绝对路径前缀
     * @param entityType 实体类类型
     */
    public DefaultOneToOneYamlDaoImpl(String path , Class<T> entityType , YamlTransaction yamlTransaction) {
        super(entityType,yamlTransaction);
        String yamlFileName = getYamlFileName(path, entityType);

        //是否需要初始化文件
        boolean flag = false;
        if (!new File(yamlFileName).exists()) {
            flag = true;
        }
        baseYml = new BaseYml<>(yamlFileName,entityType,yamlTransaction);
        getAll();
        //保存初始化数据
        if (flag) {
            saveDefaultEntity();
        }
    }

    /**
     * 保存默认实体类数据
     */
    @Override
    protected void saveDefaultEntity(){
        //保存初始化数据
        if (DefaultEntityValue.class.isAssignableFrom(entityType)) {
            List<T> entitys = DefaultEntityValue.getEntitys(entityType);
            if (entitys != null && !entitys.isEmpty()) {
                if (entitys.size() > 1) {
                    throw new DaoException("OneToOne类型的实体类，只能有一条数据");
                }
                insert(entitys.get(0));
            }
        }
    }

    @Override
    public int insert(T entity) {
        Serializable id = ClassUtils.getIdByEntity(entity);
        if (id == null) {
            throw new DaoException("执行insert时失败，ID为空,实体类: ["+entity.getClass()+"]");
        }
        T t = selectById(id);
        if (t != null) {
            return 0;
        }
        baseYml.save(entity);
        //存入缓存
        putCacheOne(id,entity);
        return 1;
    }

    @Override
    public int deleteById(Serializable id) {
        throw new DaoException("该文件类型不可删除");
    }

    @Override
    public int delete(Wrapper<T> wrapper) {
        throw new DaoException("该文件类型不可删除");
    }

    @Override
    public int deleteBatchIds(Collection<? extends Serializable> idList) {
        throw new DaoException("该文件类型不可删除");
    }

    @Override
    public int updateById(T entity) {
        Serializable id = ClassUtils.getIdByEntity(entity);
        if (id == null) {
            throw new DaoException("执行updateById时失败，ID为空,实体类: ["+entity.getClass()+"]");
        }
        T t = selectById(id);
        if (t == null) {
            return 0;
        }
        updateEntity(entity,t);
        baseYml.save(t);
        //修改缓存
        putCacheOne(id,t);
        return 1;
    }

    @Override
    public int update(T entity, Wrapper<T> updateWrapper) {
        List<T> filter = filter(updateWrapper);
        int count = 0;
        for (T t : filter) {
            count += updateById(t);
        }
        return count;
    }

    @Override
    public T selectById(Serializable id) {
        T t = getCacheOne(id);
        if (t == null) {
            if (!baseYml.isExist()) {
                return null;
            }
            t = baseYml.get();
            //存入缓存
            putCacheOne(id,t);
        }
        return t;
    }

    @Override
    public List<T> selectBatchIds(Collection<? extends Serializable> idList) {
        List<T> list = new ArrayList<>();
        List<T> all = getAll();
        if (all.size() == 0) {
            return list;
        }
        if (idList != null && idList.contains(ClassUtils.getIdByEntity(all.get(0)))) {
            list.add(all.get(0));
        }
        return list;
    }

    @Override
    public T selectOne(Wrapper<T> queryWrapper , boolean throwEx) {
        List<T> filter = filter(queryWrapper);
        if (filter.isEmpty()) {
            return null;
        }
        if (throwEx && filter.size() > 1){
            throw new DaoException("查询不到不止一条记录");
        }
        return filter.get(0);
    }

    @Override
    public long selectCount(Wrapper<T> queryWrapper) {
        List<T> filter = filter(queryWrapper);
        return filter.size();
    }

    @Override
    public List<T> selectList(Wrapper<T> queryWrapper) {
        return filter(queryWrapper);
    }

    @Override
    public Page<T> selectPage(Page<T> page, Wrapper<T> queryWrapper) {
        List<T> filter = filter(queryWrapper);
        return PageUtil.page(filter,page.getCurrentPage(),page.getItemNum());
    }

    @Override
    List<T> getAll() {
        if (getCacheAll().isEmpty()) {
            List<T> list = new ArrayList<>();
            T t = baseYml.get();
            if (t != null) {
                list.add(t);
            }
            Map<Serializable, T> cache = list
                    .stream()
                    .collect(Collectors.toMap(ClassUtils::getIdByEntity, Function.identity(), (k, v) -> v));
            //存入缓存
            putCacheBatch(cache);
            return list;
        }
        return new ArrayList<>(getCacheAll());
    }

    @Override
    public T getOne() {
        return selectOne(null,true);
    }
}